package com.mingqijia.gassafety.webserver.webSocket;

import com.alibaba.fastjson.JSONObject;
import com.gap.cache.redis.RedisCache;
import com.mingqijia.gassafety.db.entity.Consumer;
import com.mingqijia.gassafety.db.entity.Organization;
import com.mingqijia.gassafety.db.mapper.ConsumerMapper;
import com.mingqijia.gassafety.shared.dto.UserFuncCodePermissionDTO;
import com.mingqijia.gassafety.webserver.service.UserPermissionService;
import com.mingqijia.gassafety.webserver.utils.ApplicationContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author zhangfei
 * @version 1.0.0
 * @ClassName WebSocketGsProcess.java
 * @Description webSocket 消息，持不同客户端消息区分
 * @createTime 2024年08月13日
 */
@Slf4j
@Controller
@ServerEndpoint(value = "/webSocket/notify/user/{spId}/{userId}/{t}")
public class WebSocketUserProcess {


    private static final String sepa = ";";

    private static ConcurrentHashMap<String, ConcurrentHashMap<String, WebSocketUserProcess>> concurrentUserHashMap
            = new ConcurrentHashMap<>(12);

    /**
     * 会话对象
     **/
    private Session session;

    @Autowired
    RedisCache redisCache;


    @OnOpen
    public void onOpen(Session session, @PathParam("spId") String spId,
                       @PathParam("userId") String userId,
                       @PathParam("t") String t) {
        //每新建立一个连接，spId为key,this为value存储到map中
        this.session = session;
        ConcurrentHashMap<String, WebSocketUserProcess> hashMap = new ConcurrentHashMap<>();
        if (null != concurrentUserHashMap && null != concurrentUserHashMap.get(spId) && !concurrentUserHashMap.get(spId).keySet().isEmpty()) {
            hashMap = concurrentUserHashMap.get(spId);
        }
        hashMap.put(spId + sepa + userId + sepa + t, this);
        concurrentUserHashMap.put(spId, hashMap);
        log.info("WebSocketUserProcess: Open a websocket. spId={}, userid={}，t={}, sessionId={}", spId, userId, t, session.getId());
    }


    @OnClose
    public void onClose(Session session,
                        @PathParam("spId") String spId,
                        @PathParam("userId") String userId,
                        @PathParam("t") String t) {
        //客户端连接关闭时，移除map中存储的键值对
        String key = spId + sepa + userId + sepa + t;
        ConcurrentHashMap<String, WebSocketUserProcess> con = concurrentUserHashMap.get(spId);
        if (con != null && !con.keySet().isEmpty()) {
            con.remove(key);
        }
        log.info("WebSocketUserProcess: close a websocket, 当前关闭回话客户端spId= {},key= {},sessionId={}", spId, key, session.getId());
    }

    /**
     * 接收到客户端消息时触发
     */
    @OnMessage
    public void onMessage(String message,
                          Session session,
                          @PathParam("spId") String spId,
                          @PathParam("userId") String userId,
                          @PathParam("t") String t) {
        log.info("WebSocketUserProcess-onMessage：WebSocketProcess={}"
                , JSONObject.toJSONString(concurrentUserHashMap));
        log.info("WebSocketUserProcess: 接收消息来自客户端client spId={},userId={},msg={},t={},sessionId={}", spId, userId, message, t, session.getId());
    }

    /**
     * 连接发生异常时候触发
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("WebSocketGsProcess：sessionId={} Error websocket:", session.getId(), error);
    }

    /**
     * 根据spid区分客户端消息
     *
     * @param spId
     * @param message
     */
    public static void sendMessage(String spId, String message,List<Organization> organizations) {
        log.info("WebSocketUserProcess-本地大屏消息通知：spId={},message={},organizations={}", spId, message, JSONObject.toJSONString(organizations));
        //根据spId,从map中获取存储的webSocket对象
        log.info("WebSocketUserProcess-sendMessage：WebSocketUserProcess={}", JSONObject.toJSONString(concurrentUserHashMap));

        ConcurrentHashMap<String, WebSocketUserProcess> concurrentMapParents=new ConcurrentHashMap<>();
        if (!CollectionUtils.isEmpty(organizations)){
            for (int i = 0; i < organizations.size(); i++) {
                String parentSpid = organizations.get(i).getParentId();
                ConcurrentHashMap<String, WebSocketUserProcess> concurrentMapParent = concurrentUserHashMap.get(parentSpid);
                log.info("WebSocketUserProcess-concurrentMapParent:{}",JSONObject.toJSONString(concurrentMapParent));
                if (concurrentMapParent!=null)concurrentMapParents.putAll(concurrentMapParent);
            }
            log.info("WebSocketUserProcess-concurrentMapParents:{}",JSONObject.toJSONString(concurrentMapParents));
        }

        ConcurrentHashMap<String, WebSocketUserProcess> concurrentMap = concurrentUserHashMap.get(spId);
        log.info("WebSocketUserProcess-concurrentMap1:{}", JSONObject.toJSONString(concurrentMap));

        if (concurrentMap==null || concurrentMap.isEmpty()){
            concurrentMap=new ConcurrentHashMap<>();
        }
        ConcurrentHashMap<String, WebSocketUserProcess> allConcurrentMap = new ConcurrentHashMap<>(concurrentMap);
        allConcurrentMap.putAll(concurrentMapParents);

        if (allConcurrentMap.isEmpty()) {
            log.error("WebSocketUserProcess-sendMessage：allConcurrentMap is empty;concurrentHashMap={}"
                    , JSONObject.toJSONString(concurrentUserHashMap));
            return;
        }
        log.info("WebSocketUserProcess-sendMessage：allConcurrentMap={}"
                , JSONObject.toJSONString(allConcurrentMap));

        JSONObject jsonObject = JSONObject.parseObject(message);
        String cityCode = null;
        String districtCode = null;
        String townCode = null;
        if (null != jsonObject.get("consumerId")) {
            ConsumerMapper consumerMapper = ApplicationContextUtils.getBean(ConsumerMapper.class);
            if( null != consumerMapper ) {
                Consumer consumer = consumerMapper.selectById(jsonObject.getIntValue("consumerId"));
                if (!ObjectUtils.isEmpty(consumer)) {
                    cityCode = consumer.getCitycode();
                    districtCode = consumer.getDistrictcode();
                    townCode = consumer.getTowncode();
                }
            }
        }

        log.info("WebSocketUserProcess-consumerId:{},cityCode:{},districtCode:{},townCode:{}",
                jsonObject.get("consumerId"),
                cityCode,
                districtCode,
                townCode);

        UserPermissionService userPermissionService = ApplicationContextUtils.getBean(UserPermissionService.class);

        for (Map.Entry<String, WebSocketUserProcess> entry : allConcurrentMap.entrySet()) {
            String s = entry.getKey();
            WebSocketUserProcess webSocketUserProcess = entry.getValue();
            boolean isSendMsg = false;
            if (!ObjectUtils.isEmpty(webSocketUserProcess)) {
                String[] spUsers = s.split(sepa);
                if ( spUsers.length >= 3 && null != jsonObject.get("consumerId") ) {
                    String userId = spUsers[1];
                    if (userPermissionService != null) {
                        UserFuncCodePermissionDTO userFuncCodePermission = userPermissionService.getUserDepartPermission(spId, userId);
                        log.info("WebSocketUserProcess-userFuncCodePermission:{}", JSONObject.toJSONString(userFuncCodePermission));
                        int authority = null == userFuncCodePermission ? 0 : userFuncCodePermission.getAuthority();
                        if (1 == authority) {
                            List<String> funcCodes = userFuncCodePermission.getFuncCodes();
                            log.info("WebSocketUserProcess-funcCodes:{}", JSONObject.toJSONString(funcCodes));
                            if (null == funcCodes || funcCodes.isEmpty()) {
                                isSendMsg = false;
                            } else if (StringUtils.isEmpty(districtCode) && StringUtils.isEmpty(townCode) && funcCodes.contains(cityCode)) {//拥有区权限
                                isSendMsg = true;
                            } else if (StringUtils.isEmpty(townCode) && funcCodes.contains(districtCode)) {//拥有街道权限
                                isSendMsg = true;
                            } else if (!StringUtils.isEmpty(townCode) && funcCodes.contains(townCode)) {//拥有商圈权限
                                isSendMsg = true;
                            } else {
                                isSendMsg = false;
                            }
                        } else {
                            isSendMsg = true;
                        }
                    } else {
                        isSendMsg = true;
                    }
                } else {
                    isSendMsg = true;
                }
                if (!isSendMsg) {
                    log.info("WebSocketUserProcess-sendMessage spUser:{}无需发送",s);
                    continue;
                }
                //当客户端是Open状态时，才能发送消息
                if (webSocketUserProcess.session.isOpen()) {
                    try {
                        webSocketUserProcess.session.getBasicRemote().sendText(message);
                        log.info("WebSocketUserProcess-sendMessage spUser:{},message:{}", s, message);
                    } catch (IOException e) {
                        log.error("WebSocketUserProcess-sendMessage-error", e);
                    }
                } else {
                    log.error("WebSocketUserProcess：websocket session={} is closed(会话关闭) ", spId);
                }
            }
        }
        //执行完清空
        allConcurrentMap.clear();
    }
}